package ldh.maker.freemaker;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateHashModel;
import ldh.database.Table;
import ldh.maker.database.TableInfo;
import ldh.maker.util.FreeMakerUtil;

import java.io.File;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

public class MapperMaker extends FreeMarkerMaker<MapperMaker>{

	private String namespace;
	private Table table;
	private String beanName;
	private boolean getById = true;
	private boolean insert = true;
	private boolean insertSelective = true;
	private boolean update = true;
	private boolean updateNotnull = true;
	private boolean delete = true;
	private boolean findByWhere = true;
	private boolean findTotalByWhere = true;
	
	protected Class<?> keyClass; //主键
	protected BeanMaker<?> keyBeanMaker; // 主键maker;
	
	private Map<String, String> typeHandlers;
	
	public MapperMaker typeHandlers(Map<String, String> typeHandlers) {
		this.typeHandlers = typeHandlers;
		return this;
	}
	
	public MapperMaker namespace(String namespace) {
		this.namespace = namespace;
		return this;
	}
	
	public MapperMaker table(Table table) {
		this.table = table;
		return this;
	}
	
	public MapperMaker beanName(String beanName) {
		this.beanName = beanName;
		return this;
	}
	
	public MapperMaker key(Class<?> keyClass, BeanMaker<?> keyBeanMaker) {
		if (keyClass != null) {
			this.keyClass = keyClass;
		} else if (keyBeanMaker != null) {
			this.keyBeanMaker = keyBeanMaker;
		}
		
		return this;
	}
	
	public MapperMaker getById(boolean getById) {
		this.getById = getById;
		return this;
	}
	
	public MapperMaker insert(boolean insert) {
		this.insert = insert;
		return this;
	}

	public MapperMaker insertSelective(boolean insertSelective){
		this.insertSelective = insertSelective;
		return this;
	}

	public MapperMaker update(boolean update) {
		this.update = update;
		return this;
	}
	
	public MapperMaker updateNotnull(boolean updateNotnull) {
		this.updateNotnull = updateNotnull;
		return this;
	}
	
	public MapperMaker delete(boolean delete) {
		this.delete = delete;
		return this;
	}
	
	public MapperMaker findByWhere(boolean findByWhere) {
		this.findByWhere = findByWhere;
		return this;
	}
	
	public MapperMaker findTotalByWhere(boolean findTotalByWhere) {
		this.findTotalByWhere = findTotalByWhere;
		return this;
	}
	
	public void data() {
		check();
		
		data.put("namespace", namespace);
		data.put("table", table);
		data.put("alias", table.getAlias());
		data.put("aliasQueryPrefix", table.getAlias() + ".");
		data.put("aliasColumnPrefix", table.getAlias() + "_");
		if(table.getAlias().equals("")) {
			data.put("aliasQueryPrefix", "");
			data.put("aliasColumnPrefix", "");
		}
		data.put("beanName", beanName);
		data.put("beanExtend", beanName + "Where");
		data.put("getById", getById);
		data.put("insert", insert);
		data.put("insertSelective", insertSelective);
		data.put("update", update);
		data.put("updateNotnull", updateNotnull);
		data.put("delete", delete);
		data.put("findByWhere", findByWhere);
		data.put("findTotalByWhere", findTotalByWhere);
		if (namespace != null) {
			int t = namespace.lastIndexOf(".");
			if (t>0){
				String baseNamespace = namespace.substring(0, t);
				data.put("baseNamespace", baseNamespace);
			}
		}
		
		if (typeHandlers != null) data.put("typeHandlers", typeHandlers);

	}

	public MapperMaker make() {
		data();
		this.out("mapper.ftl", data);
		return this;
	}
	
	protected void check() {
		if (beanName == null || beanName.trim().equals("")) {
			beanName = FreeMakerUtil.firstUpper(table.getJavaName());
		}
		if (fileName == null || fileName.trim().equals("")) {
			fileName = beanName + "Dao.xml";
		}
		super.check();
		if (this.namespace == null || namespace.trim().equals("")) {
			throw new RuntimeException("namespace must be not null!!!!!!!!!!");
		}
		if (table == null) {
			throw new RuntimeException("table must be not null!!!!!!!!!!");
		}
		if (outPath == null || outPath.trim().equals("")) {
			throw new RuntimeException("outPath must be not null!!!!!!!!!!");
		}
		
		if (keyClass != null) {
			data.put("key", keyClass.getSimpleName());
		} else if (keyBeanMaker != null) {
			data.put("key", keyBeanMaker.getSimpleName());
		}
	}
}
